package com.bwie.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.es.EsProd;
import com.bwie.mapper.DictMapper;
import com.bwie.poi.ExcelUtil;
import com.bwie.pojo.Dict;
import com.bwie.pojo.Prod;
import com.bwie.service.ProdService;
import com.bwie.mapper.ProdMapper;
import com.bwie.utils.R;
import com.bwie.vo.PageInfoVo;
import com.fasterxml.jackson.databind.util.ArrayBuilders;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.BlockingQueue;

/**
 * @author lenovo
 * @description 针对表【t_prod(商品表)】的数据库操作Service实现
 * @createDate 2025-03-26 16:23:22
 */
@Service
public class ProdServiceImpl extends ServiceImpl<ProdMapper, Prod>
        implements ProdService {

    @Autowired
    DictMapper dictMapper;

    @Autowired
    private ProdMapper prodMapper;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    HttpServletRequest request;

    @Autowired
    HttpServletResponse response;

    @Override
    public R getDictList(Integer id) {

        //--1判断缓存中是否存在
        String key = "dict_" + id;
        Boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            System.out.println("从缓存中读取");
            String dict = redisTemplate.opsForValue().get(key);
            List<Dict> distList = JSON.parseArray(dict, Dict.class);
            return R.OK(distList);
        }
        //--2不存在从数据库中查询
        List<Dict> dictList = dictMapper.selectList(
                new QueryWrapper<Dict>().lambda().
                        eq(Dict::getDictType, id).
                        orderByAsc(Dict::getDictValue)
        );
        redisTemplate.opsForValue().set("dict", JSON.toJSONString(dictList));

        return R.OK(dictList);
    }

    @Override
    public R getProdList(PageInfoVo pageInfoVo) {


        Page<Prod> page = new Page<>(pageInfoVo.getPageNum(), pageInfoVo.getPageSize());

        QueryWrapper<Prod> wrapper = new QueryWrapper<>();

        wrapper.lambda().orderByAsc(Prod::getProdId);


        Page<Prod> prodPage = prodMapper.selectPage(page, wrapper);

        return R.OK(prodPage);
    }


    @Override
    public R getProdListFromEs(PageInfoVo pageInfoVo) {

        Integer pageNum = 0;
        if (pageInfoVo.getPageNum() > 0) {
            pageNum = pageInfoVo.getPageNum() - 1;
        }
        PageRequest pageRequest = PageRequest.of(pageNum, pageInfoVo.getPageSize());
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        if (StringUtils.isNotEmpty(pageInfoVo.getKeyWord())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("prodName", pageInfoVo.getKeyWord()));
        }

        //价格区间查询
        if (pageInfoVo.getMinValue() != null) {
            boolQueryBuilder.must(QueryBuilders.rangeQuery("prodPrice").gte(pageInfoVo.getMinValue()));
        }
        if (pageInfoVo.getMaxValue() != null) {
            boolQueryBuilder.must(QueryBuilders.rangeQuery("prodPrice").lte(pageInfoVo.getMaxValue()));
        }

        //区间查询时间
        if (StringUtils.isNotEmpty(pageInfoVo.getBeginTime())) {
            boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").
                    format("yyyy-MM-dd HH:mm:ss").
                    timeZone("GMT+8").
                    gte(pageInfoVo.getBeginTime()));
        }

        if (StringUtils.isNotEmpty(pageInfoVo.getEndTime())) {
            boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").
                    format("yyyy-MM-dd HH:mm:ss").
                    timeZone("GMT+8").
                    lte(pageInfoVo.getEndTime()));
        }


        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("prodName").preTags("<front color = 'red'>").postTags("</front>");

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder).withPageable(pageRequest);
        SearchHits<EsProd> searchHits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EsProd.class);

        long total = searchHits.getTotalHits();
        ArrayList<EsProd> recods = new ArrayList<>();

        for (SearchHit<EsProd> searchHit : searchHits.getSearchHits()) {
            EsProd esProd = searchHit.getContent();

            //获取高亮的字段值
            List<String> prodNameList = searchHit.getHighlightField("prodName");
            if (prodNameList != null && prodNameList.size() > 0) {
                esProd.setProdName(prodNameList.get(0));
            }
            recods.add(esProd);
        }

        HashMap<String, Object> map = new HashMap<>();
        map.put("total", total);
        map.put("rescods", recods);

        return R.OK(map);
    }

    @Override
    public R addProd(Prod prod) {

        //根据token获取商家ID
        String token = request.getHeader("token");
        if (token == null) {
            return R.ERROR(500, "请先登录");

        }
        Claims body = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody();
        Integer userId = body.get("id", Integer.class);


        Prod one = prodMapper.selectOne(
                new QueryWrapper<Prod>().lambda().eq(Prod::getProdName, prod.getProdName())
        );
        if (one != null) {
            return R.ERROR(500, "商品已经存在");
        }

        prod.setUserId(userId);
        prod.setProdStatus(0);
        prod.setCreateTime(new Date());

        prodMapper.insert(prod);

        return R.OK();
    }

    /**
     * @param :
     * @return void
     * @author :杨珂
     * @description 导出所有
     * @date 2025/4/8 13:03
     */
    @Override
    public void exportProdExcel() {
        //创建导出对象
        ExcelUtil<Prod> excelUtil = new ExcelUtil<>(Prod.class);
        //查询数据
        List<Prod> prodList = prodMapper.selectList(null);
        //导出文件
        excelUtil.exportExcel(response, prodList, "商品列表", "商品列表");
    }

    /**
     * @param ids:
     * @return void
     * @author :杨珂
     * @description 导出选中的
     * @date 2025/4/8 13:04
     */
    @Override
    public void exportProdCheck(String ids) {
        //先把ids转换成数组
        String[] split = ids.split(",");

        ArrayList<Integer> arrayList = new ArrayList<>();

        for (String id : split) {
            arrayList.add(Integer.parseInt(id));
        }
        List<Prod> prodList = prodMapper.selectBatchIds(arrayList);
        ExcelUtil<Prod> excelUtil = new ExcelUtil<>(Prod.class);
        excelUtil.exportExcel(response, prodList, "商品列表", "商品列表");
    }


    @Override
    public R importProdExcel(MultipartFile file) {

        try {
            //创建工具类对象
            ExcelUtil<Prod> excelUtil = new ExcelUtil<>(Prod.class);

            List<Prod> prods = excelUtil.importExcel(file.getInputStream());

            System.out.println(prods);

            String msg = "成功导入" + prods.size() + "条数据";

            for (Prod prod : prods) {

                System.out.println(prod);

                if (prod.getProdId() == null) {
                    prodMapper.insert(prod);
                    continue;
                }
                Prod prodList = prodMapper.selectById(prod);
                if (prodList != null) {
                    //更新商品
                    prodMapper.updateById(prod);
                } else {
                    //不存在添加商品
                    prodMapper.insert(prod);
                }
            }

            return R.OK(msg);
        } catch (IOException e) {
            e.printStackTrace();
            return R.ERROR(500, "导入失败");
        }
    }


}




